/**
 * ObstacleFactory - 障碍物工厂
 * 负责创建和管理各种类型的障碍物实例
 */

import { Obstacle, ObstacleType } from '../Obstacle'
import { BarrierObstacle, BarrierVariant, BarrierObstacleOptions } from './BarrierObstacle'
import { PitObstacle, PitVariant, PitObstacleOptions } from './PitObstacle'
import { MovingObstacle, MovementPattern, MovingObstacleOptions } from './MovingObstacle'

/**
 * 障碍物创建配置
 */
export interface ObstacleConfig {
  type: ObstacleType
  x: number
  y: number
  width?: number
  height?: number
  variant?: string
  difficulty?: number
  [key: string]: any
}

/**
 * 障碍物模板定义
 */
interface ObstacleTemplate {
  type: ObstacleType
  defaultWidth: number
  defaultHeight: number
  variants: string[]
  minDifficulty: number
  maxDifficulty: number
}

/**
 * 障碍物工厂类
 * @class
 * @example
 * const factory = new ObstacleFactory();
 * const barrier = factory.createObstacle({
 *   type: ObstacleType.BARRIER,
 *   x: 400,
 *   y: 300,
 *   variant: 'high'
 * });
 */
export class ObstacleFactory {
  private templates: Map<ObstacleType, ObstacleTemplate> = new Map()
  private difficultyMultiplier: number = 1.0

  /**
   * 创建障碍物工厂实例
   */
  constructor() {
    this.initializeTemplates()
  }

  /**
   * 初始化障碍物模板
   */
  private initializeTemplates(): void {
    // 栅栏障碍物模板
    this.templates.set(ObstacleType.BARRIER, {
      type: ObstacleType.BARRIER,
      defaultWidth: 20,
      defaultHeight: 60,
      variants: Object.values(BarrierVariant),
      minDifficulty: 1,
      maxDifficulty: 3
    })

    // 坑洞障碍物模板
    this.templates.set(ObstacleType.PIT, {
      type: ObstacleType.PIT,
      defaultWidth: 80,
      defaultHeight: 40,
      variants: Object.values(PitVariant),
      minDifficulty: 2,
      maxDifficulty: 4
    })

    // 移动障碍物模板
    this.templates.set(ObstacleType.MOVING, {
      type: ObstacleType.MOVING,
      defaultWidth: 40,
      defaultHeight: 40,
      variants: Object.values(MovementPattern),
      minDifficulty: 3,
      maxDifficulty: 5
    })
  }

  /**
   * 创建障碍物
   * @param config - 障碍物配置
   * @returns 创建的障碍物实例
   */
  createObstacle(config: ObstacleConfig): Obstacle {
    const template = this.templates.get(config.type)
    if (!template) {
      throw new Error(`不支持的障碍物类型: ${config.type}`)
    }

    // 合并默认配置
    const finalConfig = this.mergeWithDefaults(config, template)

    // 根据类型创建具体的障碍物
    switch (config.type) {
      case ObstacleType.BARRIER:
        return this.createBarrierObstacle(finalConfig)
      case ObstacleType.PIT:
        return this.createPitObstacle(finalConfig)
      case ObstacleType.MOVING:
        return this.createMovingObstacle(finalConfig)
      default:
        throw new Error(`未实现的障碍物类型: ${config.type}`)
    }
  }

  /**
   * 创建栅栏障碍物
   * @param config - 配置信息
   * @returns 栅栏障碍物实例
   */
  private createBarrierObstacle(config: ObstacleConfig): BarrierObstacle {
    const options: BarrierObstacleOptions = {
      x: config.x,
      y: config.y,
      width: config.width!,
      height: config.height!,
      variant: (config.variant as BarrierVariant) || BarrierVariant.HIGH
    }

    return new BarrierObstacle(options)
  }

  /**
   * 创建坑洞障碍物
   * @param config - 配置信息
   * @returns 坑洞障碍物实例
   */
  private createPitObstacle(config: ObstacleConfig): PitObstacle {
    const options: PitObstacleOptions = {
      x: config.x,
      y: config.y,
      width: config.width!,
      height: config.height!,
      variant: (config.variant as PitVariant) || PitVariant.MEDIUM,
      hasSpikes: config.hasSpikes || false
    }

    return new PitObstacle(options)
  }

  /**
   * 创建移动障碍物
   * @param config - 配置信息
   * @returns 移动障碍物实例
   */
  private createMovingObstacle(config: ObstacleConfig): MovingObstacle {
    const options: MovingObstacleOptions = {
      x: config.x,
      y: config.y,
      width: config.width!,
      height: config.height!,
      movementPattern: (config.variant as MovementPattern) || MovementPattern.HORIZONTAL,
      speed: config.speed || 50,
      amplitude: config.amplitude || 30,
      frequency: config.frequency || 1
    }

    return new MovingObstacle(options)
  }

  /**
   * 合并默认配置
   * @param config - 用户配置
   * @param template - 模板配置
   * @returns 合并后的配置
   */
  private mergeWithDefaults(config: ObstacleConfig, template: ObstacleTemplate): ObstacleConfig {
    return {
      ...config,
      width: config.width || template.defaultWidth,
      height: config.height || template.defaultHeight,
      variant: config.variant || this.getRandomVariant(template),
      difficulty: config.difficulty || 1
    }
  }

  /**
   * 获取随机变体
   * @param template - 障碍物模板
   * @returns 随机变体
   */
  private getRandomVariant(template: ObstacleTemplate): string {
    const variants = template.variants
    return variants[Math.floor(Math.random() * variants.length)]
  }

  /**
   * 根据难度创建随机障碍物
   * @param x - X坐标
   * @param y - Y坐标
   * @param difficulty - 难度等级 (1-5)
   * @returns 随机障碍物实例
   */
  createRandomObstacle(x: number, y: number, difficulty: number = 1): Obstacle {
    // 根据难度筛选可用的障碍物类型
    const availableTypes = Array.from(this.templates.entries())
      .filter(([_, template]) => 
        difficulty >= template.minDifficulty && difficulty <= template.maxDifficulty
      )
      .map(([type, _]) => type)

    if (availableTypes.length === 0) {
      // 如果没有合适的类型，使用栅栏作为默认
      availableTypes.push(ObstacleType.BARRIER)
    }

    // 随机选择障碍物类型
    const randomType = availableTypes[Math.floor(Math.random() * availableTypes.length)]
    
    // 创建配置
    const config: ObstacleConfig = {
      type: randomType,
      x,
      y,
      difficulty
    }

    // 根据难度调整属性
    this.adjustConfigByDifficulty(config, difficulty)

    return this.createObstacle(config)
  }

  /**
   * 根据难度调整配置
   * @param config - 障碍物配置
   * @param difficulty - 难度等级
   */
  private adjustConfigByDifficulty(config: ObstacleConfig, difficulty: number): void {
    // const difficultyFactor = Math.min(difficulty / 5, 1) // 标准化到0-1

    switch (config.type) {
      case ObstacleType.BARRIER:
        // 高难度时更多使用双重栅栏
        if (difficulty >= 3 && Math.random() < 0.3) {
          config.variant = BarrierVariant.DOUBLE
        }
        break

      case ObstacleType.PIT:
        // 高难度时增加尖刺坑洞的概率
        if (difficulty >= 4 && Math.random() < 0.4) {
          config.variant = PitVariant.SPIKE
          config.hasSpikes = true
        }
        // 根据难度调整坑洞大小
        config.width = 60 + (difficulty * 10)
        break

      case ObstacleType.MOVING:
        // 高难度时使用更复杂的移动模式
        if (difficulty >= 4) {
          const complexPatterns = [MovementPattern.CIRCULAR, MovementPattern.ZIGZAG]
          config.variant = complexPatterns[Math.floor(Math.random() * complexPatterns.length)]
        }
        // 根据难度调整移动速度
        config.speed = 30 + (difficulty * 15)
        config.amplitude = 20 + (difficulty * 10)
        break
    }
  }

  /**
   * 创建障碍物组合
   * @param x - 起始X坐标
   * @param y - 起始Y坐标
   * @param difficulty - 难度等级
   * @returns 障碍物数组
   */
  createObstacleGroup(x: number, y: number, difficulty: number = 1): Obstacle[] {
    const obstacles: Obstacle[] = []
    const groupSize = Math.min(Math.floor(difficulty / 2) + 1, 3) // 1-3个障碍物

    for (let i = 0; i < groupSize; i++) {
      const offsetX = i * 100 // 障碍物间距
      const obstacle = this.createRandomObstacle(x + offsetX, y, difficulty)
      obstacles.push(obstacle)
    }

    return obstacles
  }

  /**
   * 获取障碍物模板信息
   * @param type - 障碍物类型
   * @returns 模板信息
   */
  getTemplate(type: ObstacleType): ObstacleTemplate | undefined {
    return this.templates.get(type)
  }

  /**
   * 获取所有支持的障碍物类型
   * @returns 障碍物类型数组
   */
  getSupportedTypes(): ObstacleType[] {
    return Array.from(this.templates.keys())
  }

  /**
   * 设置难度倍数
   * @param multiplier - 难度倍数
   */
  setDifficultyMultiplier(multiplier: number): void {
    this.difficultyMultiplier = Math.max(0.1, multiplier)
  }

  /**
   * 获取当前难度倍数
   * @returns 难度倍数
   */
  getDifficultyMultiplier(): number {
    return this.difficultyMultiplier
  }

  /**
   * 验证障碍物配置
   * @param config - 障碍物配置
   * @returns 是否有效
   */
  validateConfig(config: ObstacleConfig): boolean {
    // 检查必需字段
    if (!config.type || config.x === undefined || config.y === undefined) {
      return false
    }

    // 检查类型是否支持
    if (!this.templates.has(config.type)) {
      return false
    }

    // 检查变体是否有效
    const template = this.templates.get(config.type)!
    if (config.variant && !template.variants.includes(config.variant)) {
      return false
    }

    return true
  }

  /**
   * 获取工厂统计信息
   * @returns 统计信息
   */
  getStats(): {
    supportedTypes: number
    totalVariants: number
    difficultyRange: { min: number, max: number }
  } {
    let totalVariants = 0
    let minDifficulty = Infinity
    let maxDifficulty = -Infinity

    for (const template of this.templates.values()) {
      totalVariants += template.variants.length
      minDifficulty = Math.min(minDifficulty, template.minDifficulty)
      maxDifficulty = Math.max(maxDifficulty, template.maxDifficulty)
    }

    return {
      supportedTypes: this.templates.size,
      totalVariants,
      difficultyRange: { min: minDifficulty, max: maxDifficulty }
    }
  }
}